
import java_cup.runtime.*;

%%

%class Lexer
%unicode
%cup
%line
%column

%{
  StringBuffer string = new StringBuffer();

  private Symbol symbol(int type) {return new Symbol(type, yyline, yycolumn); }
  private Symbol symbol(int type, Object value) {return new Symbol(type, yyline, yycolumn, value); }
  
%}

LineTerminator = \r|\n|\r\n
WhiteSpace     = {LineTerminator} | [ \t\f]

/* comments */
Comment = "(*" [^*] ~"*)" | "(*" "*"+ ")"

Identifier = [a-zA-Z] [a-zA-Z_0-9]*

DecIntegerLiteral = [0-9]+

%state STRING

%%

/* keywords */
<YYINITIAL> "and"              	{ return symbol(sym.AND); }
<YYINITIAL> "begin"             { return symbol(sym.BEGIN); }
<YYINITIAL> "bool"              { return symbol(sym.BOOL); }
<YYINITIAL> "class"             { return symbol(sym.CLASS); }
<YYINITIAL> "do"              	{ return symbol(sym.DO); }
<YYINITIAL> "else"              { return symbol(sym.ELSE); }
<YYINITIAL> "end"              	{ return symbol(sym.END); }
<YYINITIAL> "false"             { return symbol(sym.FALSE); }
<YYINITIAL> "if"              	{ return symbol(sym.IF); }
<YYINITIAL> "inherits"          { return symbol(sym.INHERITS); }
<YYINITIAL> "int"              	{ return symbol(sym.INT); }
<YYINITIAL> "new"              	{ return symbol(sym.NEW); }
<YYINITIAL> "not"              	{ return symbol(sym.NOT); }
<YYINITIAL> "null"              { return symbol(sym.NULL); }
<YYINITIAL> "or"              	{ return symbol(sym.OR); }
<YYINITIAL> "then"              { return symbol(sym.THEN); }
<YYINITIAL> "this"              { return symbol(sym.THIS); }
<YYINITIAL> "true"              { return symbol(sym.TRUE); }
<YYINITIAL> "let"              	{ return symbol(sym.LET); }
<YYINITIAL> "in"        		{ return symbol(sym.IN); }
<YYINITIAL> "while"             { return symbol(sym.WHILE); }
<YYINITIAL> "string"            { return symbol(sym.STRING); }
<YYINITIAL> "unit"              { return symbol(sym.UNIT); }
<YYINITIAL> "nop"              	{ return symbol(sym.NOP); }

<YYINITIAL> {Identifier}       				{ return symbol(sym.IDENTIFIER, yytext()); }
<YYINITIAL> {DecIntegerLiteral}      		{ return symbol(sym.INTEGER_LITERAL,new Integer (yytext())); }
<YYINITIAL> \"                 				{ string.setLength(0); yybegin(STRING); }

<YYINITIAL>  "("                            { return symbol(sym.LPAR); }
<YYINITIAL>  ")"                            { return symbol(sym.RPAR); }
<YYINITIAL>  ","                            { return symbol(sym.COMMA); }
<YYINITIAL>  ";"                            { return symbol(sym.SEMICOLON); }
<YYINITIAL>  "."                            { return symbol(sym.DOT); }
<YYINITIAL>  "-"                            { return symbol(sym.MINUS); }
<YYINITIAL>  "+"                            { return symbol(sym.PLUS); }
<YYINITIAL>  "*"                            { return symbol(sym.STAR); }
<YYINITIAL>  "/"                            { return symbol(sym.SLASH); }
<YYINITIAL>  "="                           	{ return symbol(sym.EQUAL); }
<YYINITIAL>  ">"                            { return symbol(sym.GT); }
<YYINITIAL>  ">="                           { return symbol(sym.GE); }
<YYINITIAL>  "<"                            { return symbol(sym.LT); }
<YYINITIAL>  "<="                           { return symbol(sym.LE); }
<YYINITIAL>  "<>"                           { return symbol(sym.NEQUAL); }
<YYINITIAL>  ":="                           { return symbol(sym.ASSIGN); }

<YYINITIAL>  {Comment}                      { /* ignore */ }
 
<YYINITIAL>  {WhiteSpace}                   { /* ignore */ }

<YYINITIAL>  <<EOF>>                        { return null; }


<STRING>
{
  \"                             { yybegin(YYINITIAL); return symbol(sym.STRING_LITERAL,string.toString()); }
  [^\n\"\\]+                     { string.append( yytext() ); }
  \\n                            { string.append('\n'); }
  \\\"                           { string.append('\"'); }
  \\\\                           { string.append('\\'); }
}

/* error fallback */
.|\n                             { throw new Error("Illegal character <"+
                                                    yytext()+">"); }
